﻿#include "Sudoku.h"
#include<vector>
using namespace std;

Sudoku::Sudoku(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::SudokuClass())
{
    QFont font = QFont("Microsoft YaHei", 14, 2);
    ui->setupUi(this);
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            QTextEdit* PFirst = new QTextEdit(ui->widget);
            PFirst->setFont(font);
            PFirst->setGeometry(i * 40, j * 40, 40, 40);
        }
    }
    
}

Sudoku::~Sudoku()
{
    delete ui;
}

class Solution {
public:
    bool can_place(const vector<vector<char>>& board, int row, int col, char num)
    {
        for (int i = 0; i < 9; i++)
        {
            if (num == board[row][i] || num == board[i][col])
                return false;
        }

        int row_area = row / 3 * 3;
        int col_area = col / 3 * 3;

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (board[row_area + i][col_area + j] == num)
                    return false;
            }
        }

        return true;
    }

    bool _solveSudoku(vector<vector<char>>& board, int row, int col)
    {
        while (board[row][col] != '.')
        {
            if (row == 8 && col == 8)
                return true;

            if (col == 8)
            {
                col = 0;
                row++;
            }
            else
            {
                col++;
            }
        }

        for (char i = '1'; i <= '9'; i++)
        {
            if (can_place(board, row, col, i))
            {
                board[row][col] = i;
                if (_solveSudoku(board, row, col))
                {
                    return true;
                }

                board[row][col] = '.';
            }
        }

        return false;
    }

    bool solveSudoku(vector<vector<char>>& board) {
        return (_solveSudoku(board, 0, 0));
    }
};

void Sudoku::on_confirm_clicked()
{
    qDebug() << "confirm" << endl;
    vector<vector<char>> sudoku;
    for (int i = 0; i < 9; i++)
    {   
        vector<char> ins;
        for (int j = 0; j < 9; j++)
        {
            
            QTextEdit* tmp = (QTextEdit*)ui->widget->children().at(i * 9 + j);

            string&& s = tmp->toPlainText().toStdString();

            if (s.size() == 0)
            {
                ins.push_back('.');
            }
            else if (s.size() != 1 || s[0] < '0' || s[0] > '9')
            {
                QMessageBox::warning(this, QStringLiteral("Error!"), QStringLiteral("Please input number from '1~9'"), QMessageBox::Cancel);
                return;
            }
            else
                ins.push_back(s[0]);
        }

        sudoku.push_back(ins);
    }

    if (Solution().solveSudoku(sudoku))
    {
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                QTextEdit* tmp = (QTextEdit*)ui->widget->children().at(i * 9 + j);

                tmp->setText(QString(sudoku[i][j]));
            }
        }
    }
    else
    {
        QMessageBox::warning(this, QStringLiteral("Remind"), QStringLiteral("No right solutions"), QMessageBox::Cancel);
    }
}

void Sudoku::on_clear_clicked()
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            QTextEdit* tmp = (QTextEdit*)ui->widget->children().at(i * 9 + j);

            tmp->clear();
        }
    }
}